import * as G6 from "@antv/g6";
import responseTimeImg from "@/assets/images/topoNodes/responseTime.png";
import requestImg from "@/assets/images/topoNodes/request.png";
import errorRateImg from "@/assets/images/topoNodes/errorRate.png";
import namespaceImg from "@/assets/images/topoNodes/namespace.png";
import noFlowDataImg from "@/assets/images/topoNodes/noFlowData.svg";
import simpleNodeImg from "@/assets/images/topoNodes/simpleNode.svg";
import entranceImg from "@/assets/images/topoNodes/entrance.svg";
import alarmImg from "@/assets/images/topoNodes/alarm.svg";
import { formatUnit } from "@/utils/format";
import {
  fittingString,
  formatDodRingData,
  getNodeAndEdgeStatus,
  wordLength,
} from "./topoService";
import { forEach } from "lodash";

const NodeW = 210,
  NodeH = 122;
export const MaxTime = 60 * 60000; // 超过1小时不展示同环比数据
// 节点卡片中要展示的指标
const nodeMetricList = [
  {
    label: "响应时间",
    value: "responseTime",
    dod: "responseTimeDodRate",
    ring: "responseTimeRingRate",
    icon: responseTimeImg,
    unit: "ns",
  },
  {
    label: "请求量",
    value: "requestTotal",
    dod: "requestTotalDodRate",
    ring: "requestTotalRingRate",
    icon: requestImg,
    unit: "count",
  },
  {
    label: "错误率",
    value: "errorRate",
    dod: "errorRateDodRate",
    ring: "errorRateRingRate",
    icon: errorRateImg,
    unit: "%",
  },
];
export const statusColorMap = {
  1: "#F7313B",
  0: "#13C2C2",
};
const strokeColorMap = {
  1: "#F7313B",
  0: "#acbce2",
}
const nodeBgColorMap = {
  1: "#fbe7e8",
  0: "#e7effb",
}
const nodeNameColorMap = {
  1: "#FF4850",
  0: "#0F5EF7",
}
// register custom node
G6.registerNode(
  "custom-node",
  {
    draw: (node, group) => {
      const status = getNodeAndEdgeStatus(node);
      // 整体外框
      const shape = group.addShape("rect", {
        attrs: {
          x: 0,
          y: 0,
          width: NodeW,
          height: NodeH,
          radius: 2,
          cursor: "pointer",
          fill: nodeBgColorMap[status],
          lineWidth: 1,
          strokeOpacity: 1,
          stroke: strokeColorMap[status],
          shadowBlur: 4,
          shadowColor: "rgba(0, 0, 0, 0.1)",
        },
        name: "node-warp",
        id: "node-warp",
        draggable: true,
      });
      if (node?.errorMessage?.length) {
        // 告警铃铛
        group.addShape("image", {
          attrs: {
            x: 180,
            y: 10,
            width: 25,
            height: 20,
            img: alarmImg,
            cursor: "pointer",
          },
          id: "alarm-img",
          name: "alarm-img",
          draggable: true,
        });
      }

      // 节点名称
      group.addShape("text", {
        attrs: {
          x: 12,
          y: 27,
          text:
            node.topoViewType === "pod"
              ? fittingString(node.podName, 200, 14)
              : fittingString(node.nameBak || node.workloadName, 150, 14),
          fontSize: 14,
          fill: nodeNameColorMap[status],
        },
        id: "node-name",
        name: "node-name",
        draggable: true,
      });
      if (node.topoViewType !== "pod") {
        // 入口节点标识
        group.addShape("image", {
          attrs: {
            x: 108,
            y: 10,
            width: 20,
            height: 20,
            img: node.isEntrance ? entranceImg : "",
          },
          id: "entrance-img",
          name: "entrance-img",
          draggable: true,
        });
        // 命名空间暂时不展示了
        // // 命名空间外框
        // group.addShape('rect', {
        //     attrs: {
        //         x: 132,
        //         y: 10,
        //         width: 76,
        //         height: 20,
        //         radius: 2,
        //         fill: '#F4F4F4',
        //         lineWidth: 1,
        //         stroke: 'rgba(0, 0, 0, 0.2)',
        //     },
        //     name: 'namespace-warp',
        //     id: 'namespace-warp',
        //     draggable: true
        // });
        // // 命名空间图标
        // group.addShape('image', {
        //     attrs: {
        //         x: 136,
        //         y: 13,
        //         width: 14,
        //         height: 14,
        //         img: namespaceImg,
        //     },
        //     id: 'namespace-img',
        //     name: 'namespace-img',
        //     draggable: true,
        // });
        // // 命名空间名字
        // group.addShape('text', {
        //     attrs: {
        //         x: 152,
        //         y: 26,
        //         text: fittingString(node.namespace, 52, 12),
        //         fontSize: 12,
        //         fontWeight: 400,
        //         fill: 'rgba(0, 0, 0, 0.65)',
        //     },
        //     id: 'namespace-name',
        //     name: 'namespace-name',
        //     draggable: true,
        // });
      }
      // 不是无数据节点才绘制节点数据
      console.log(node.attachDataType, "attachDataType in node");
      if (!node.isNoData) {
        // 节点的响应时间、请求量、错误率
        forEach(nodeMetricList, (metric, idx) => {
          const { label, value, dod, ring, icon, unit } = metric;

          const percent = node.attachDataType ? node[dod] : node[ring];
          group.addShape("rect", {
            attrs: {
              x: 12,
              y: 38 + idx * 24,
              width: NodeW - 24,
              height: 20,
              fill: 'white'
            },
            id: "metric-bg",
            name: "metric-bg",
          });
          group.addShape("image", {
            attrs: {
              x: 12,
              y: 43 + idx * 24,
              width: 12,
              height: 12,
              img: icon,
            },
            id: `${value}-metric-img`,
            name: `${value}-metric-img`,
            draggable: true,
          });

          // label名称
          group.addShape("text", {
            attrs: {
              x: 28,
              y: 55 + idx * 24,
              text: label,
              fontSize: 12,
              fontWeight: 400,
              fill: "rgba(0, 0, 0, 0.25)",
            },
            id: `${value}-metric-label`,
            name: `${value}-metric-label`,
            draggable: true,
          });
          // 当前值
          group.addShape("text", {
            attrs: {
              x: 84,
              y: 56 + idx * 24,
              text: formatUnit(node[value], unit, 1),
              fontSize: 14,
              fontWeight: 500,
              fill: "rgba(0, 0, 0, 0.85)",
            },
            id: `${value}-metric-value`,
            name: `${value}-metric-value`,
            draggable: true,
          });
          // 同比环比值
          group.addShape("text", {
            attrs: {
              x: 148,
              y: 55 + idx * 24,
              // 0也要展示出来，不能展示--
              text: formatDodRingData(percent),
              fontSize: 12,
              fontWeight: 400,
              fill:
                node.timeRange > MaxTime ? "#FFFFFF" : "rgba(0, 0, 0, 0.65)",
            },
            id: `${value}-metric-percent`,
            name: `${value}-metric-percent`,
            draggable: true,
          });
          // 0不需要展示上下箭头
          if (percent && percent !== "NaN") {
            // 上下箭头
            group.addShape("marker", {
              attrs: {
                x: 200,
                y: 50 + idx * 24,
                r: 3,
                symbol: percent > 0 ? "triangle" : "triangle-down",
                fill:
                  node.timeRange > MaxTime
                    ? "#FFFFFF"
                    : percent > 0
                    ? "#F7313B"
                    : "#13C2C2",
              },
              id: `${value}-metric-marker`,
              name: `${value}-metric-marker`,
              draggable: true,
            });
          }
        });
      }
      // 底部状态线
      // group.addShape("rect", {
      //   attrs: {
      //     x: 0,
      //     y: NodeH - 4,
      //     width: NodeW,
      //     height: 4,
      //     radius: [0, 0, 4, 4],
      //     fill: statusColorMap[status],
      //   },
      //   name: "node-footer",
      //   id: "node-footer",
      //   draggable: true,
      // });
      // 若是无数据节点-绘制无数据图，将上面的内容覆盖
      if (node.isNoData) {
        group.addShape("image", {
          attrs: {
            x: 12,
            y: 35,
            width: 188,
            height: 78,
            img: noFlowDataImg,
            cursor: "pointer",
          },
          id: "node-noData-img",
          name: "node-noData-img",
          draggable: true,
        });
      }

      return shape;
    },
    afterDraw: (cfg, group) => {
      // 更新入口节点位置-紧跟节点名称后面
      const nodeNameBox = group.findById("node-name").getBBox();
      const entranceImage = group.findById("entrance-img");
      if (entranceImage) {
        entranceImage.attr({
          x: nodeNameBox.maxX + 4,
        });
      }
      // 不是无数据节点才更新指标元素
      if (!cfg.isNoData) {
        forEach(nodeMetricList, (metric) => {
          const { value } = metric;
          const metricPercentBox = group
            .findById(`${value}-metric-percent`)
            .getBBox();
          const metricMarker = group.findById(`${value}-metric-marker`);
          if (metricMarker) {
            // 指标的上下箭头紧跟百分比之后
            metricMarker.attr({
              x: metricPercentBox.maxX + 6,
            });
          }
        });
      }
    },
    update: (cfg, node) => {
      const group = node.getContainer();
      // 切换同环比后需要重新更新节点状态
      const status = getNodeAndEdgeStatus(cfg);
      // 节点外框
      const nodeWarp = group.findById("node-warp");
      nodeWarp.attr({ stroke: strokeColorMap[status] });
      // 节点名称
      const nodeName = group.findById("node-name");
      nodeName.attr({ fill: nodeNameColorMap[status] });
      // 节点footer
      const nodeFooter = group.findById("node-footer");
      nodeFooter?.attr({ fill: strokeColorMap[status] });
      // 节点入口标识
      const entranceImage = group.findById("entrance-img");
      if (entranceImage) {
        entranceImage.attr({
          img: cfg.isEntrance ? entranceImg : "",
        });
      }
      // 不是无数据节点才更新指标元素
      if (!cfg.isNoData) {
        // 更新同环比数据
        forEach(nodeMetricList, (metric, idx) => {
          const { value, dod, ring } = metric;
          const percent = cfg.attachDataType ? cfg[dod] : cfg[ring];
          const metricPercent = group.findById(`${value}-metric-percent`);
          const metricMarker = group.findById(`${value}-metric-marker`);
          metricPercent.attr({
            // 0也要展示出来，不能展示--
            text: formatDodRingData(percent),
          });
          if (metricMarker) {
            // 先remove掉metric-marker上下箭头
            group.removeChild(metricMarker);
          }
          // 0不需要展示上下箭头
          if (percent && percent !== "NaN") {
            // 重新设置上下箭头
            group.addShape("marker", {
              attrs: {
                x: 200,
                y: 50 + idx * 24,
                r: 3,
                symbol: percent > 0 ? "triangle" : "triangle-down",
                fill:
                  cfg.timeRange > MaxTime
                    ? "#FFFFFF"
                    : percent > 0
                    ? "#F7313B"
                    : "#acbce2",
              },
              id: `${value}-metric-marker`,
              name: `${value}-metric-marker`,
              draggable: true,
            });
          }
        });
      }
    },
    afterUpdate(cfg, node) {
      const group = node.getContainer();
      // 不是无数据节点才更新指标元素
      if (!cfg.isNoData) {
        forEach(nodeMetricList, (metric) => {
          const { value } = metric;
          const metricPercentBox = group
            .findById(`${value}-metric-percent`)
            .getBBox();
          const metricMarker = group.findById(`${value}-metric-marker`);
          if (metricMarker) {
            // 指标的上下箭头紧跟百分比之后
            metricMarker.attr({
              x: metricPercentBox.maxX + 6,
            });
          }
        });
      }
    },
    setState: (name, value, item) => {
      const group = item.getContainer();
      const state = item.getStates();
      const nodeWarp = group.findById("node-warp");
      if (!nodeWarp) {
        return;
      }
      const stateHandlers = {
        hover: function (value) {
          if (value) {
            nodeWarp.attr({
              // strokeOpacity: 1,
              lineWidth: 2,
            });
          } else {
            nodeWarp.attr({
              // strokeOpacity: 1,
              lineWidth: 1,
            });
          }
        },
      };
      // console.log(name, 'statename', );

      stateHandlers[name]?.(value);
      if (state.length === 0 && nodeWarp) {
        // nodeWarp.attr({
        //   strokeOpacity: 0,
        // });
      }
    },
    getAnchorPoints() {
      return [
        [0.5, 0],
        [0.5, 1],
      ];
    },
  },
  "single-node"
);
// register custom node
G6.registerNode(
  "circle-node",
  {
    draw: (node, group) => {
      const statusColorMap = {
        1: "#F7313B",
        0: "#898e9e",
      };
      const status = getNodeAndEdgeStatus(node);
      // 整体外框

      const maxFieldValue = node.maxSortFieldValue;
      const scale = Math.min(Number(((node[node.sortField] || 0) / maxFieldValue + 1).toFixed(2)), 2);
      console.log(scale, "scale");

      const shape = group.addShape("circle", {
        attrs: {
          x: 0,
          y: 0,

          radius: 4,
          r: 20 * (scale),
          cursor: "pointer",
          fill: "#FFFFFF",
          lineWidth: 1,
          strokeOpacity: 1,
          stroke: statusColorMap[status],
          shadowBlur: 4,
          shadowColor: "rgba(0, 0, 0, 0.1)",
        },
        name: "node-warp",
        id: "node-warp",
        draggable: true,
      });
      group.addShape("image", {
        attrs: {
          x: -10,
          y: -10,
          width: 20,
          height: 20,
          img: simpleNodeImg,
        },
        id: "node-img",
        name: "node-img",
        draggable: false,
      });
      const letterWidth =
        node.topoViewType === "pod"
          ? wordLength(nodePodName, 100, 14)
          : wordLength(node.nameBak || node.workloadName, 140, 14);
      // console.log(width, 'letterWidth');
      console.log(group.getBBox(), 'group', group.getCanvasBBox(),node.name);
      const {width, height} = group.getBBox()
      console.log(height, 'height');

      // 节点名称
      group.addShape("text", {
        attrs: {
          x: -(letterWidth) / 2,
          y: 20*scale + 18,
          text:
            node.topoViewType === "pod"
              ? fittingString(node.podName, 100, 14)
              : fittingString(node.nameBak || node.workloadName, 140, 14),
          fontSize: 14,
          fill: statusColorMap[status],
        },
        id: "node-name",
        name: "node-name",
        draggable: true,
      });
      if (node.topoViewType !== "pod") {
        // 入口节点标识
        group.addShape("image", {
          attrs: {
            x: 108,
            y: 10,
            width: 20,
            height: 20,
            img: node.isEntrance ? entranceImg : "",
          },
          id: "entrance-img",
          name: "entrance-img",
          draggable: true,
        });
        // 命名空间暂时不展示了
        // // 命名空间外框
        // group.addShape('rect', {
        //     attrs: {
        //         x: 132,
        //         y: 10,
        //         width: 76,
        //         height: 20,
        //         radius: 2,
        //         fill: '#F4F4F4',
        //         lineWidth: 1,
        //         stroke: 'rgba(0, 0, 0, 0.2)',
        //     },
        //     name: 'namespace-warp',
        //     id: 'namespace-warp',
        //     draggable: true
        // });
        // // 命名空间图标
        // group.addShape('image', {
        //     attrs: {
        //         x: 136,
        //         y: 13,
        //         width: 14,
        //         height: 14,
        //         img: namespaceImg,
        //     },
        //     id: 'namespace-img',
        //     name: 'namespace-img',
        //     draggable: true,
        // });
        // // 命名空间名字
        // group.addShape('text', {
        //     attrs: {
        //         x: 152,
        //         y: 26,
        //         text: fittingString(node.namespace, 52, 12),
        //         fontSize: 12,
        //         fontWeight: 400,
        //         fill: 'rgba(0, 0, 0, 0.65)',
        //     },
        //     id: 'namespace-name',
        //     name: 'namespace-name',
        //     draggable: true,
        // });
      }
      // 不是无数据节点才绘制节点数据
      return shape;
    },
    afterDraw: (cfg, group) => {
      // 更新入口节点位置-紧跟节点名称后面
      const nodeNameBox = group.findById("node-name").getBBox();
      const entranceImage = group.findById("entrance-img");
      if (entranceImage) {
        entranceImage.attr({
          x: nodeNameBox.maxX + 4,
          y: nodeNameBox.y,
        });
      }
      // 不是无数据节点才更新指标元素
      // if (!cfg.isNoData) {
      //     forEach(nodeMetricList, metric => {
      //         const { value } = metric;
      //         const metricPercentBox = group.findById(`${value}-metric-percent`).getBBox();
      //         const metricMarker = group.findById(`${value}-metric-marker`);
      //         if (metricMarker) {
      //             // 指标的上下箭头紧跟百分比之后
      //             metricMarker.attr({
      //                 x: metricPercentBox.maxX + 6
      //             })
      //         }
      //     })
      // }
    },
    update: (cfg, node) => {
      const group = node.getContainer();
      // 切换同环比后需要重新更新节点状态
      const status = getNodeAndEdgeStatus(cfg);
      // 节点外框
      const nodeWarp = group.findById("node-warp");
      nodeWarp.attr({ stroke: strokeColorMap[status] });
      // 节点名称
      const nodeName = group.findById("node-name");
      nodeName.attr({ fill: nodeNameColorMap[status] });
      // 节点footer
      const nodeFooter = group.findById("node-footer");
      nodeFooter?.attr({ fill: statusColorMap[status] });
      // 节点入口标识
      const entranceImage = group.findById("entrance-img");
      if (entranceImage) {
        entranceImage.attr({
          img: cfg.isEntrance ? entranceImg : "",
        });
      }
    },
    afterUpdate(cfg, node) {
      const group = node.getContainer();
      // 不是无数据节点才更新指标元素
      // if (!cfg.isNoData) {
      //     forEach(nodeMetricList, metric => {
      //         const { value } = metric;
      //         const metricPercentBox = group.findById(`${value}-metric-percent`).getBBox();
      //         const metricMarker = group.findById(`${value}-metric-marker`);
      //         if (metricMarker) {
      //             // 指标的上下箭头紧跟百分比之后
      //             metricMarker.attr({
      //                 x: metricPercentBox.maxX + 6
      //             })
      //         }
      //     })
      // }
    },
    setState: (name, value, item) => {
      const group = item.getContainer();
      const state = item.getStates();
      const nodeWarp = group.findById("node-warp");
      if (!nodeWarp) {
        return;
      }
      const stateHandlers = {
        hover: function (value) {
          if (value) {
            nodeWarp.attr({
              strokeOpacity: 0.65,
            });
          } else {
            nodeWarp.attr({
              strokeOpacity: 1,
            });
          }
        },
      };
      // console.log(name, 'statename', );

      stateHandlers[name]?.(value);
      // if (state.length === 0 && nodeWarp) {
      //     nodeWarp.attr({
      //         strokeOpacity: 0,
      //     });
      // }
    },
    getAnchorPoints() {
      return [
        [0.5, 0],
        [0.5, 1],
      ];
    },
  },
  "single-node"
);
const EditNodeW = 164,
  EditNodeH = 68;
const MoreCircle = [0, 1, 2];
// register custom edit node
G6.registerNode(
  "custom-edit-node",
  {
    draw: (node, group) => {
      // 整体外框
      const shape = group.addShape("rect", {
        attrs: {
          x: 0,
          y: 0,
          width: EditNodeW,
          height: EditNodeH,
          radius: 4,
          cursor: "pointer",
          fill: "#FFFFFF",
          lineWidth: node.inSystem ? 1 : 0,
          stroke: "#226EE7",
          shadowOffsetY: 0,
          shadowBlur: 4,
          shadowColor: "rgba(0, 0, 0, 0.1)",
        },
        name: "node-warp",
        id: "node-warp",
        draggable: true,
      });
      // 节点名称
      group.addShape("text", {
        attrs: {
          x: 12,
          y: 27,
          text: fittingString(node.nameBak || node.workloadName, 110, 14),
          fontSize: 14,
          fontWeight: 500,
          fill: "rgba(0, 0, 0, 0.85)",
        },
        id: "node-name",
        name: "node-name",
        draggable: true,
      });
      // 入口节点标识
      group.addShape("image", {
        attrs: {
          x: 12,
          y: 34,
          width: 20,
          height: 20,
          img: node.isEntrance ? entranceImg : "",
        },
        id: "entrance-img",
        name: "entrance-img",
        draggable: true,
      });
      // 命名空间外框
      group.addShape("rect", {
        attrs: {
          x: 12 + (node.isEntrance ? 24 : 0),
          y: 34,
          width: 85,
          height: 20,
          radius: 2,
          fill: "#F4F4F4",
          lineWidth: 1,
          stroke: "rgba(0, 0, 0, 0.2)",
        },
        name: "namespace-warp",
        id: "namespace-warp",
        draggable: true,
      });
      // 命名空间图标
      group.addShape("image", {
        attrs: {
          x: 16 + (node.isEntrance ? 24 : 0),
          y: 37,
          width: 14,
          height: 14,
          img: namespaceImg,
        },
        id: "namespace-img",
        name: "namespace-img",
        draggable: true,
      });
      // 命名空间名字
      group.addShape("text", {
        attrs: {
          x: 32 + (node.isEntrance ? 24 : 0),
          y: 50,
          text: fittingString(node.namespace, 52, 12),
          fontSize: 12,
          fontWeight: 400,
          fill: "rgba(0, 0, 0, 0.65)",
        },
        id: "namespace-name",
        name: "namespace-name",
        draggable: true,
      });
      // more-warp
      group.addShape("rect", {
        attrs: {
          x: 134,
          y: 8,
          width: 24,
          height: 24,
          radius: 4,
          fill: "#FFFFFF",
          opacity: 0,
          cursor: "pointer",
        },
        id: "node-more-warp",
        name: "node-more-warp",
        draggable: true,
      });
      // more
      forEach(MoreCircle, (idx) => {
        group.addShape("circle", {
          attrs: {
            x: 146,
            y: 15 + idx * 5,
            r: 1,
            fill: "#FFFFFF",
            cursor: "pointer",
          },
          id: `node-more-${idx}`,
          name: `node-more-${idx}`,
          draggable: true,
        });
      });

      return shape;
    },

    update: (cfg, node) => {
      const group = node.getContainer();
      // 更新是否加入系统的边框样式
      const nodeWarp = group.findById("node-warp");
      nodeWarp.attr({
        lineWidth: cfg.inSystem ? 1 : 0,
      });
      // 节点重命名更新节点名称
      const nodeName = group.findById("node-name");
      nodeName.attr({
        text: fittingString(cfg.nameBak || cfg.workloadName, 110, 14),
      });
      // 更新节点入口标识和命名空间的位置
      const entranceImage = group.findById("entrance-img");
      const namespaceWarp = group.findById("namespace-warp");
      const namespaceImage = group.findById("namespace-img");
      const namespaceName = group.findById("namespace-name");
      entranceImage.attr({
        img: cfg.isEntrance ? entranceImg : "",
      });
      namespaceWarp.attr({
        x: 12 + (cfg.isEntrance ? 24 : 0),
      });
      namespaceImage.attr({
        x: 16 + (cfg.isEntrance ? 24 : 0),
      });
      namespaceName.attr({
        x: 32 + (cfg.isEntrance ? 24 : 0),
      });
    },
    setState: (name, value, item) => {
      const group = item.getContainer();
      const nodeWarp = group.findById("node-warp");
      const stateHandlers = {
        hover: function (value) {
          forEach(MoreCircle, (idx) => {
            const nodeMoreItem = group.findById(`node-more-${idx}`);
            nodeMoreItem.attr({
              fill: value ? "#000000" : "#FFFFFF",
            });
          });
          nodeWarp.attr({
            shadowOffsetY: value ? 4 : 0,
            shadowBlur: value ? 6 : 4,
            shadowColor: value ? "rgba(0, 0, 0, 0.2)" : "rgba(0, 0, 0, 0.1)",
          });
        },
        moreActive: function (value) {
          forEach(MoreCircle, (idx) => {
            const nodeMoreItem = group.findById(`node-more-${idx}`);
            nodeMoreItem.attr({
              fill: value ? "#226EE7" : "#000000",
            });
          });
          const nodeMoreWarp = group.findById("node-more-warp");
          nodeMoreWarp.attr({
            fill: value ? "#F8F8F9" : "#FFFFFF",
          });
        },
      };
      stateHandlers[name](value);
    },
  },
  "single-node"
);

const MergeNodeW = 130,
  MergeNodeH = 68;
// register merge view topo custom node
G6.registerNode(
  "custom-merge-node",
  {
    draw: (node, group) => {
      // 整体外框
      const shape = group.addShape("rect", {
        attrs: {
          x: 0,
          y: 0,
          width: MergeNodeW,
          height: MergeNodeH,
          radius: 4,
          cursor: "pointer",
          fill: "#FFFFFF",
          shadowOffsetY: 0,
          shadowBlur: 4,
          shadowColor: "rgba(0, 0, 0, 0.1)",
        },
        name: "node-warp",
        id: "node-warp",
        draggable: true,
      });
      // 节点名称
      group.addShape("text", {
        attrs: {
          x: 12,
          y: 27,
          text: fittingString(node.nameBak || node.workloadName, 110, 14),
          fontSize: 14,
          fontWeight: 500,
          fill: "rgba(0, 0, 0, 0.85)",
        },
        id: "node-name",
        name: "node-name",
        draggable: true,
      });
      // 入口节点标识
      group.addShape("image", {
        attrs: {
          x: 12,
          y: 34,
          width: 20,
          height: 20,
          img: node.isEntrance ? entranceImg : "",
        },
        id: "entrance-img",
        name: "entrance-img",
        draggable: true,
      });
      // 命名空间外框
      group.addShape("rect", {
        attrs: {
          x: 12 + (node.isEntrance ? 24 : 0),
          y: 34,
          width: 85,
          height: 20,
          radius: 2,
          fill: "#F4F4F4",
          lineWidth: 1,
          stroke: "rgba(0, 0, 0, 0.2)",
        },
        name: "namespace-warp",
        id: "namespace-warp",
        draggable: true,
      });
      // 命名空间图标
      group.addShape("image", {
        attrs: {
          x: 16 + (node.isEntrance ? 24 : 0),
          y: 37,
          width: 14,
          height: 14,
          img: namespaceImg,
        },
        id: "namespace-img",
        name: "namespace-img",
        draggable: true,
      });
      // 命名空间名字
      group.addShape("text", {
        attrs: {
          x: 32 + (node.isEntrance ? 24 : 0),
          y: 50,
          text: fittingString(node.namespace, 52, 12),
          fontSize: 12,
          fontWeight: 400,
          fill: "rgba(0, 0, 0, 0.65)",
        },
        id: "namespace-name",
        name: "namespace-name",
        draggable: true,
      });

      return shape;
    },

    setState: (name, value, item) => {
      const group = item.getContainer();
      const nodeWarp = group.findById("node-warp");
      const stateHandlers = {
        hover: function (value) {
          nodeWarp.attr({
            shadowOffsetY: value ? 4 : 0,
            shadowBlur: value ? 6 : 4,
            shadowColor: value ? "rgba(0, 0, 0, 0.2)" : "rgba(0, 0, 0, 0.1)",
          });
        },
        active: function (value) {
          nodeWarp.attr({
            fill: value ? "rgba(34, 110, 231, 0.12)" : "#FFFFFF",
          });
        },
      };
      stateHandlers[name](value);
    },
  },
  "single-node"
);
